﻿using System;
using System.Collections.Generic;
using System.Text;
using Sinacor.Infra.Service.Data;
using PSE.ProcessManager.Server.Process.Security;
using Sinacor.Infra.Core.ProcessManager.Server.Security;
using System.Data.Common;
using System.Data;
using Sinacor.Infra.Service.Common;

namespace Sinacor.Process.Bovespa.Distribuicao.Server.ResourceAccess
{
    public class Exportacao : BaseResourceAccess
    {
        #region Contrutor

        public Exportacao()
            : base(AuthenticationContext<SinacorAuthenticationData>.Current.AuthenticationData.CompanyId)
        {
        }

        #endregion


        #region Métodos Públicos

        public void ExcluirErrosExportacao()
        {
            StringBuilder sql = new StringBuilder();

            sql.Append(@"DELETE TBOERRO");

            using (DbCommand command = this.DataBase.GetSqlStringCommand(sql.ToString()))
            {
                this.DataBase.ExecuteNonQuery(command);
            }
        }

        public List<ProcessEntity.DistribuicaoDetail> ConsultarDistribuicaoExportar(ProcessEntity.Parameter.FiltroExportacaoDistribuicao entity)
        {
            List<ProcessEntity.DistribuicaoDetail> retorno = null;
            StringBuilder sql = new StringBuilder();

            sql.Append(@"Select
                               'B' TipoRegistro,
                               b.cd_negocio CodigoNegociacao,
                               a.cd_clie_outr_bolsa CodigoCliente,
                               a.dv_clie_outr_bolsa DigitoCliente,
                               b.qt_qtdesp QuantidadePercentual,
                               d.vl_negocio PrecoNegocio,
                               b.cd_natope NaturezaOperacao,
                               b.cd_carliq CarteiraLiquidacao, 
                               decode(b.in_liquida,null,
                                      decode(c.cd_empr_bolsa,null,b.cd_usufim,to_number(c.cd_empr_bolsa)),
                                      b.cd_usufim) CustodianteArbitragem,
                               decode(b.in_liquida,null,
                                     decode(c.cd_empr_bolsa,null,to_number(b.cd_clifim),b.cd_cliente),
                                     to_number(b.cd_clifim)) ClienteCustodianteArbitragem,
                               decode(b.in_liquida,null,
                                      decode(c.cd_empr_bolsa,null,b.dv_clifim,e.dv_cliente),
                                      b.dv_clifim) DigitoCustodianteArbitragem,
                               nvl(decode(b.in_liquida,null,
                                      decode(c.cd_empr_bolsa,null,b.in_liquida,'C'),b.in_liquida),' ') TipoLiquidacao,
                               b.cd_bolsamov BolsaNegocio,
                               d.tp_vcoter PrazoTermo,
                               b.nr_seqord NumeroOrdem,
                               b.cd_cliente ClienteBolsa,
                               decode(nvl(a.in_util_corresp,'N'),'S',nvl(a.cd_cliente,-1),-1) CodigoCliOutraBolsa
                        from torcomi b, tornegd d, tsccboutp a, tgelocal c, tscclibol e
                         where b.dt_negocio      = :DataPregao
                           and b.in_corresp      = 'N'
                           and b.cd_corresp      = :CodigoCorrespondente
                           and d.cd_negocio      = b.cd_negocio
                           and d.nr_negocio      = b.nr_negocio
                           and d.cd_bolsamov     = b.cd_bolsamov
                           and d.cd_natope       = b.cd_natope
                           and d.dt_pregao       = b.dt_negocio
                           and (    (    substr( d.cd_codisi, 7, 2 ) <> 'PP'
                                     and tp_liquid                   <> 'POP' )
                                 or (    substr( d.cd_codisi, 7, 2 ) = 'PP'
                                     and tp_liquid                   = 'POP' ) )
                           and c.cd_empresa      = :CodigoEmpresa
                           and c.cd_bolsa        = b.cd_bolsamov
                           and e.cd_cliente      = b.cd_cliente
                           and b.cd_cliente      = a.cd_cliente(+)
                           and 'S'               = a.in_util_corresp(+)
                           and b.cd_corresp      = to_number(a.cd_membro(+))
                           and decode(b.cd_bolsamov,'5','1','8','1',b.cd_bolsamov) = decode(a.cd_bolsa(+),'SP','1','RJ','2','BH','6','0')");

            using (DbCommand command = this.DataBase.GetSqlStringCommand(sql.ToString()))
            {
                this.DataBase.AddInParameter(command, "DataPregao", DbType.Date, entity.DataPregao);
                this.DataBase.AddInParameter(command, "CodigoEmpresa", DbType.Int32, AuthenticationContext<SinacorAuthenticationData>.Current.AuthenticationData.CompanyId);
                this.DataBase.AddInParameter(command, "CodigoCorrespondente", DbType.Int32, entity.CodigoCorrespondente);

                retorno = this.FindAll<ProcessEntity.DistribuicaoDetail>(command,
                    reader =>
                    {
                        ProcessEntity.DistribuicaoDetail item = new ProcessEntity.DistribuicaoDetail();

                        item.TipoRegistro = reader.GetValue<String>("TipoRegistro");
                        item.CodigoISIN = reader.GetValue<String>("CodigoNegociacao");
                        
                        item.CodigoCliente = reader.IsDBNull(reader.GetOrdinal("CodigoCliente")) ? 0 :  reader.GetValue<Int32>("CodigoCliente");

                        if (!reader.IsDBNull(reader.GetOrdinal("DigitoCliente")))
                            item.DigitoCliente = reader.GetValue<Int16>("DigitoCliente");
                        
                        item.Quantidade = reader.GetValue<Decimal>("QuantidadePercentual");
                        item.PrecoNegocio = reader.GetValue<Decimal?>("PrecoNegocio");
                        item.NaturezaOperacao = EnumConverter.Parse<ProcessEntity.Enum.NaturezaOperacao>(reader.GetValue<String>("NaturezaOperacao"));
                        item.CarteiraLiquidacao = reader.GetValue<Int16>("CarteiraLiquidacao");
                        item.CustodianteArbitragem = reader.IsDBNull(reader.GetOrdinal("CustodianteArbitragem")) ? 0 : reader.GetValue<Int32>("CustodianteArbitragem");
                        item.ClienteCustodianteArbitragem = reader.IsDBNull(reader.GetOrdinal("ClienteCustodianteArbitragem")) ? 0 : reader.GetValue<Int32>("ClienteCustodianteArbitragem");

                        if (!reader.IsDBNull(reader.GetOrdinal("DigitoCustodianteArbitragem")))
                            item.DigitoCustodianteArbitragem = reader.GetValue<Int16>("DigitoCustodianteArbitragem");
                        
                        item.TipoLiquidacao = EnumConverter.Parse<ProcessEntity.Enum.TipoLiquidacao>(reader.GetValue<String>("TipoLiquidacao"));
                        item.BolsaNegocio = EnumConverter.Parse<ProcessEntity.Enum.BolsaNegocio>(reader.GetValue<String>("BolsaNegocio"));
                        //item.PercentualAcrescimo
                        item.PrazoTermo = reader.IsDBNull(reader.GetOrdinal("PrazoTermo")) ? 0 : reader.GetValue<Int32>("PrazoTermo");
                        item.NumeroOrdem = reader.GetValue<Int32>("NumeroOrdem");
                        item.CodigoClienteOutraBolsa = reader.GetValue<Int32>("CodigoCliOutraBolsa");

                        return item;
                    });
            }

            return retorno;
        }

        public void InserirErroDistribuicao(ProcessEntity.Parameter.FiltroErro entity)
        {
            StringBuilder sql = new StringBuilder();

            sql.Append(@"insert into tboerro
                       ( dt_datmov, dt_pregao, cd_cliente, cd_bolsamov, cd_praca, ds_erro )
                      values
                       ( :DataMovimento, :DataPregao, :CodigoCliente, :CodigoBolsa, :Praca, :DescricaoErro )");

            using(DbCommand command = this.DataBase.GetSqlStringCommand(sql.ToString()))
            {
                this.DataBase.AddInParameter(command, "DataMovimento", DbType.Date, entity.DataMovimento);
                this.DataBase.AddInParameter(command, "DataPregao", DbType.Date, entity.DataPregao);
                this.DataBase.AddInParameter(command, "CodigoCliente", DbType.Int32, entity.CodigoCliente);
                this.DataBase.AddInParameter(command, "CodigoBolsa", DbType.AnsiString, entity.CodigoBolsa);
                this.DataBase.AddInParameter(command, "Praca", DbType.AnsiString, entity.Praca);
                this.DataBase.AddInParameter(command, "DescricaoErro", DbType.AnsiString, entity.DescricaoErro);

                this.DataBase.ExecuteNonQuery(command);
            }
        }

        public bool VerificarCorrespondente(ProcessEntity.Parameter.FiltroExportacaoDistribuicao entity)
        {
            StringBuilder sql = new StringBuilder();
            int retorno = 0;

            sql.Append(@"select count(*)
                        FROM TORCOMI B, TORNEGD D
                        where B.DT_NEGOCIO     = :DataPregao
                          AND B.CD_CORRESP     = :CodigoCorrespondente
                          AND B.IN_CORRESP     = 'N'
                          AND B.CD_CORRESP     = D.CD_CORRESP
                          AND D.CD_NEGOCIO     = B.CD_NEGOCIO 
                          AND D.NR_NEGOCIO     = B.NR_NEGOCIO 
                          AND D.CD_BOLSAMOV    = B.CD_BOLSAMOV 
                          AND D.CD_NATOPE      = B.CD_NATOPE 
                          AND D.DT_PREGAO      = B.DT_NEGOCIO");

            using (DbCommand command = this.DataBase.GetSqlStringCommand(sql.ToString()))
            {
                this.DataBase.AddInParameter(command, "CodigoCorrespondente", DbType.Int32, entity.CodigoCorrespondente);
                this.DataBase.AddInParameter(command, "DataPregao", DbType.Date, entity.DataPregao);

                retorno = Convert.ToInt32(this.DataBase.ExecuteScalar(command));
            }

            return (retorno > 0);
        }

        #endregion
    }
}
